package org.lboot.jpa.jpa;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;

import org.lboot.jpa.service.BaseService;
import org.lboot.jpa.service.BatchService;
import org.lboot.jpa.service.UnwrapService;
import org.lboot.core.domain.ErrMsg;
import org.lboot.core.domain.PageResultDTO;
import org.lboot.core.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author kindear
 * @version 1.0.0
 * @warn 非稳定方法
 */
public abstract class AbstractJpaCurd<KeyType,Entity extends Serializable,D extends JpaRepository<Entity,KeyType>> implements BaseService<Entity,KeyType>, UnwrapService<Entity,KeyType>, BatchService<Entity,KeyType> {
    @Autowired(required = false)
    protected D dao;

    @Override
    public PageResultDTO<Entity> getAll(Pageable pageable, Example<Entity> example) {
        Page<Entity> page;

        if(Validator.isEmpty(example)){
            page = dao.findAll(pageable);
        }
        else {
            page = dao.findAll(example,pageable);
        }
        /*
         * 获取分页主体内容
         */
        List<Entity> list = page.getContent();
        PageResultDTO<Entity> pageResultDTO = new PageResultDTO<>();


        //封装分页请求结果
        pageResultDTO.setContent(list);
        pageResultDTO.setSize(page.getSize());
        pageResultDTO.setTotalPages(page.getTotalPages());
        pageResultDTO.setNumber(page.getNumber());
        pageResultDTO.setTotalElements(page.getTotalElements());
        return pageResultDTO;
    }

    @Override
    public PageResultDTO<Entity> getAll(Pageable pageable) {
        Page<Entity> page;
        page = dao.findAll(pageable);
        /*
         * 获取分页主体内容
         */
        List<Entity> list = page.getContent();
        PageResultDTO<Entity> pageResultDTO = new PageResultDTO<>();
        //封装分页请求结果
        pageResultDTO.setContent(list);
        pageResultDTO.setSize(page.getSize());
        pageResultDTO.setTotalPages(page.getTotalPages());
        pageResultDTO.setNumber(page.getNumber());
        pageResultDTO.setTotalElements(page.getTotalElements());
        return pageResultDTO;
    }

    @Override
    public List<Entity> getAll(Example<Entity> example) {
        return dao.findAll(example);
    }

    @Override
    public List<Entity> getExample(Example<Entity> example) {
        return dao.findAll(example);
    }

    @Override
    public void deleteOne(KeyType k) {
        dao.deleteById(k);
    }

    @Override
    public Optional<Entity> getOne(KeyType k) {
        return dao.findById(k);
    }

    @Override
    public Entity saveOne(Entity v) {
        Map<String,Object> maps = BeanUtil.beanToMap(v);
        if (Validator.isNotEmpty(maps.get("id"))){
            throw new BusinessException(HttpStatus.BAD_REQUEST, ErrMsg.build("新建参数不可携带ID"));
        }
        return dao.save(v);
    }

    @Override
    public Entity updateOne(Entity v) {
        Map<String,Object> maps = BeanUtil.beanToMap(v);
        if (Validator.isEmpty(maps.get("id"))){
            throw new BusinessException(HttpStatus.BAD_REQUEST,ErrMsg.build("更新参数需要携带ID"));
        }
        return dao.save(v);
    }

    @Override
    public Entity getOneUnwrap(KeyType k) {
        Optional<Entity> op = getOne(k);
        if (!op.isPresent()) throw new BusinessException(HttpStatus.NOT_FOUND,ErrMsg.build("未查询到对应信息"));
        return op.get();
    }

    @Override
    public List<Entity> batchGet(List<KeyType> list) {
        return dao.findAllById(list);
    }

    @Override
    @Transactional
    public void batchDelete(List<KeyType> list) {
        dao.deleteAllById(list);
    }


    @Override
    @Transactional
    public List<Entity> batchSave(List<Entity> list) {
        return dao.saveAll(list);
    }

    @Override
    public List<Entity> getAll() {
        return dao.findAll();
    }
}
